//
//  HTTPTool.swift
//  YSM
//
//  Created by ys on 2018/8/3.
//  Copyright © 2018年 ys. All rights reserved.
//

import UIKit
import Alamofire

func Log<T>(_ message:T, file:String = #file, method:String = #function, line:Int = #line){
//    #if DEBUG
    if   let path = NSURL(string: file)
    {
        print("\(path.lastPathComponent!)[\(line)],\(method) \(message)")
    }
//    #endif
}

typealias completed = ((_ result: ResultInfo) -> Void)

class HTTPTool: NSObject {

    static let sharedInstance = HTTPTool()
    
    private var dicTask = [String: DataRequest]()
    
    /// 网络请求个数
    private var taskCount = 0
    
    /// 是否需要菊花转动
    private var needNetworkActivityIndicator = true
    
    private override init() {
        
    }
    
}

// MARK: - action: get
extension HTTPTool {
    /// get (url, params, header, httpName, closure)
    static func get(url:String, params:[String: Any]? = nil, header:[String: Any]? = nil, httpName:String? = nil, closure: completed?) {
        
        let _ = HTTPTool.sharedInstance.request(url: url, params: params, header: header, httpName:httpName, isPOST: false, closure: closure)
        
    }
}

// MARK: - action: post
extension HTTPTool {
    /// post (url, params, header, httpName, closure)
    static func post(url:String, params:[String: Any]? = nil, header:[String: Any]? = nil, httpName:String? = nil, closure: completed?) {
        
        let _ = HTTPTool.sharedInstance.request(url: url, params: params, header: header, httpName:httpName, isPOST: true, closure: closure)
        
    }
}

// MARK: - action: request
extension HTTPTool {
    
    /// request
    static func request(url:String, params:[String:Any]? = nil, header:[String:Any]? = nil, httpName:String? = nil, isPOST:Bool = false, closure: completed? = nil) -> Void {
        
        HTTPTool.sharedInstance.request(url: url, params: params, header: header, httpName:httpName, isPOST: isPOST, closure: closure)
    }
    
    /// file
    static func requestFile(url:String, params:[String:Any]? = nil, header:[String: Any]? = nil, imgs:[(name: String, img: Any)], httpName:String?, closure: completed? = nil) {
        if imgs.count == 0 {
            HTTPTool.sharedInstance.request(url: url, params: params, header: header, httpName:httpName, isPOST: true, closure: closure)
            return
        }
        HTTPTool.sharedInstance.requestFile(url: url, params: params, header: header, imgs: imgs, httpName: httpName, isPOST: true, closure: closure)
    }
}

// MARK: - private
extension HTTPTool {
    
    //
    private func request(url:String, params:[String:Any]?, header:[String:Any]?, httpName:String?, isPOST:Bool, closure: completed?) -> Void {
        
        let method = isPOST ? HTTPMethod.post : HTTPMethod.get
        
        var headerNew: HTTPHeaders = [:]
        if let h = header {
            for obj in h {
                headerNew[obj.key] = headerNew[obj.value as? String ?? ""]
            }
        }
        
        let task = Alamofire.request(url, method: method, parameters: params, encoding: URLEncoding.default, headers: headerNew).response {[weak self] (response) in
            if response.error == nil {
                // 请求成功
                let res = ResultInfo.convertPHPResponseNorToResultInfo(response: response.data)
                if closure != nil {
                    closure!(res)
                }
                
            } else {
                // 失败
                print("请求失败\(String(describing: response.error))")
            }
            
            //网络请求-1
            self?.decreaseTaskCount()
            self?.delTaskId(httpName: httpName)
        }
        
        if httpName != nil {
            dicTask[httpName!] = task
        }
        
        // 网络请求+1
        increaseTaskCount()
        
    }
    
    // 文件提交
    private func requestFile(url:String, params:[String:Any]?, header:[String:Any]?, imgs: [(name: String, img:Any)], httpName:String?, isPOST:Bool, closure: completed?) -> Void {
        let method = isPOST ? HTTPMethod.post : HTTPMethod.get
        
        var headerNew: HTTPHeaders = [:]
        if let h = header {
            for obj in h {
                headerNew[obj.key] = headerNew[obj.value as? String ?? ""]
            }
        }
        
        Alamofire.upload(multipartFormData: { (formdata) in
            var index = 0
            for (name, obj) in imgs {
                var data: Data?
                if obj is UIImage {
                    data = UIImageJPEGRepresentation(obj as! UIImage, 0.8)!
                }
                if obj is Data {
                    data = obj as? Data
                }
                if data == nil {continue}
                
                //                let name = "img[]"
                //                let fileName = "image\(index).jpg"
                let name = name
                let fileName = "\(name).jpg"
                formdata.append(data!, withName: name, fileName: fileName, mimeType: "image/jpeg")
                index += 1
            }
        }, usingThreshold: (20*1024*1024), to: url, method: method, headers: headerNew) {[weak self] (encodingResult) in
            switch encodingResult {
            case .success(let uploadFile, _, _):
                //上传进度回调
                uploadFile.uploadProgress(closure: { (progress) in
                    debugPrint("上传进度\(progress)")
                })
                //上传结果回调
                uploadFile.responseString(completionHandler: { (response) in
                    
                    if response.error == nil {
                        // 请求成功
                        let res = ResultInfo.convertPHPResponseNorToResultInfo(response: response.data)
                        if closure != nil {
                            closure!(res)
                        }
                        
                    } else {
                        // 失败
                        print("请求失败\(String(describing: response.error))")
                    }
                })
                
                break
            case .failure( let error):
                print(error);
                break
            }
            
            //网络请求-1
            self?.decreaseTaskCount()
            self?.delTaskId(httpName: httpName)
        }
        
        // 网络请求+1
        increaseTaskCount()
        
    }
}

// MARK: - 取消网络请求
extension HTTPTool {
    
    /// 通过httpName取消单个网络请求
    static func cancelSigleTask(httpName: String) {
        HTTPTool.sharedInstance.cancelSigleTask(httpName: httpName)
    }
    
    /// 取消当前controller所有网络请求
    static func cancelSigleControllerTask(httpName: String) {
        HTTPTool.sharedInstance.cancelSigleControllerTask(httpName: httpName)
    }
    
    /// 取消所有网络请求
    static func cancelAllTask() {
        for obj in HTTPTool.sharedInstance.dicTask {
            HTTPTool.sharedInstance.cancelSigleTask(httpName: obj.key)
        }
    }
    
    // 取消网络请求，根据key删除字典dicTask里面的value
    private func cancelSigleTask(httpName: String) {
        for (k,v) in dicTask{
            Log("k是\(k)的请求会取消")
            if(k.hasPrefix(httpName)){
                v.cancel()
                Log("k是\(k)的请求已经取消")
                delTaskId(httpName: httpName)
            }
        }
        //        if let task = dicTask[httpName] {
        //            task.cancel()
        //            delTaskId(httpName: httpName)
        //           Log(message:"\(httpName) 已经成功取消")
        //        }
    }
    
    // 取消当前class的所有网络请求
    private func cancelSigleControllerTask(httpName: String) {
        for (k,v) in dicTask{
            if k.hasPrefix(httpName){
                v.cancel()
                delTaskId(httpName: httpName)
                //                Log(message:"\(httpName) 已经成功取消")
            }
        }
    }
    
    private func delTaskId(httpName: String?) {
        if httpName != nil {
            _ = dicTask.removeValue(forKey: httpName!)
            //            if let value = dicTask.removeValue(forKey: httpName) {
            //                Log(message:"The value \(value) was removed.\(httpName)")
            //            }
        }
    }
    
    /// 网络请求总数+1
    private func increaseTaskCount() {
        // 加线程安全?
        taskCount += 1
        toggleNetworkActivityIndicator()
    }
    
    /// 网络请求总数-1
    private func decreaseTaskCount() {
        // 加线程安全?
        taskCount -= 1
        toggleNetworkActivityIndicator()
    }
    
    /// 判断菊花转动
    private func toggleNetworkActivityIndicator() {
        //        Log(message:"当前网络请求个数 = \(taskCount)")
        if needNetworkActivityIndicator {
            DispatchQueue.main.async { [weak self] in
                UIApplication.shared.isNetworkActivityIndicatorVisible = self?.taskCount ?? 0 > 0
            }
        }
        
    }
}

extension NSObject{
    var httpTokenRandom:String{
        get{
            let token = "\(type(of:self))\(arc4random())"
            //            Log(message:"httpTokenRandom = \(token)")
            return token
        }
    }
    
    var httpToken:String{
        get{
            return "\(type(of:self))"
        }
    }
}
